package top.dyzmj.microbench.microbench;

import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.dyzmj.detty.core.utils.SystemPropertyUtil;
import top.dyzmj.detty.core.utils.concurrent.DefaultThreadFactory;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 描述:
 *	MH微基准测试适配器的默认实现。这个装置可能会引入上下文开关
 * @author dongYu
 * @date 2021/11/23
 */
@Fork(AbstractMicrobenchmark.DEFAULT_FORKS)
public class AbstractMicrobenchmark extends AbstractMicrobenchmarkBase {

	protected static final int DEFAULT_FORKS = 2;

	public static final class HarnessExecutor extends ThreadPoolExecutor {
		private final Logger logger = LoggerFactory.getLogger(AbstractMicrobenchmark.class);

		public HarnessExecutor(int maxThreads, String prefix) {
			super(maxThreads, maxThreads, 0, TimeUnit.MILLISECONDS,
					new LinkedBlockingQueue<>(), new DefaultThreadFactory(prefix));
			logger.debug("Using harness executor");
		}
	}

	private final String[] jvmArgs;

	public AbstractMicrobenchmark() {
		this(false, false);
	}

	public AbstractMicrobenchmark(boolean disableAssertions) {
		this(disableAssertions, false);
	}

	public AbstractMicrobenchmark(boolean disableAssertions, boolean disableHarnessExecutor) {
		final String[] customArgs;
		if (disableHarnessExecutor) {
			customArgs = new String[]{"-Xms768m", "-Xmx768m", "-XX:MaxDirectMemorySize=768m",
					"-XX:BiasedLockingStartupDelay=0"};
		} else {
			customArgs = new String[]{"-Xms768m", "-Xmx768m", "-XX:MaxDirectMemorySize=768m",
					"-XX:BiasedLockingStartupDelay=0",
					"-Djmh.executor=CUSTOM",
					"-Djmh.executor.class=top.dyzmj.microbench.microbench.AbstractMicrobenchmark$HarnessExecutor"};
		}
		String[] jvmArgs = new String[BASE_JVM_ARGS.length + customArgs.length];
		System.arraycopy(BASE_JVM_ARGS, 0, jvmArgs, 0, BASE_JVM_ARGS.length);
		System.arraycopy(customArgs, 0, jvmArgs, BASE_JVM_ARGS.length, customArgs.length);
		if (disableAssertions) {
			jvmArgs = removeAssertions(jvmArgs);
		}
		this.jvmArgs = jvmArgs;
	}

	@Override
	protected String[] jvmArgs() {
		return jvmArgs;
	}

	@Override
	protected ChainedOptionsBuilder newOptionsBuilder() throws Exception {
		ChainedOptionsBuilder runnerOptions = super.newOptionsBuilder();
		if (getForks() > 0) {
			runnerOptions.forks(getForks());
		}

		return runnerOptions;
	}

	protected int getForks() {
		return SystemPropertyUtil.getInt("forks", -1);
	}
}
